package cn.geminis.workflow.service.service.engine.listener;

import cn.geminis.workflow.service.service.engine.ExtensionElementUtils;
import cn.geminis.workflow.service.service.engine.expression.ExpressionValueContext;
import cn.geminis.workflow.service.service.engine.expression.GeminiExpression;
import cn.geminis.workflow.service.service.engine.expression.GeminiExpressionManager;
import cn.geminis.workflow.service.service.model.RemoteDataService;
import cn.geminis.workflow.service.utils.SpringUtils;
import lombok.RequiredArgsConstructor;
import org.flowable.common.engine.api.delegate.event.FlowableEntityEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.impl.cfg.TransactionState;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class ProcessCompletedListener implements FlowableEventListener {

    private final ApplicationContext context;
    private final GeminiExpressionManager expressionManager;
    private final RemoteDataService remoteDataService;

    @Override
    public void onEvent(FlowableEvent flowableEvent) {
        var processInstance = (ProcessInstance) ((FlowableEntityEvent) flowableEvent).getEntity();
        var process = context.getBean(ProcessEngine.class)
                .getRepositoryService()
                .getBpmnModel(processInstance.getProcessDefinitionId())
                .getMainProcess();
        var extensionElements = process.getExtensionElements();
        ExtensionElementUtils.get(extensionElements, "eventUrl")
                .ifPresent(eventUrl -> {
                    var valueContext = SpringUtils.getBean(ExpressionValueContext.class)
                            .withProcess(processInstance);
                    valueContext.getVariables().put("eventType", flowableEvent.getType().name());

                    var eventUrlExpression = ((GeminiExpression) expressionManager.createExpression(eventUrl));
                    eventUrl = (String) eventUrlExpression.getValue(null);
                    var eventValue = ExtensionElementUtils.get(extensionElements, "eventValue")
                            .orElse("");
                    var eventValueExpression = ((GeminiExpression) expressionManager.createExpression(eventValue));
                    eventValue = (String) eventValueExpression.getValue(null);

                    remoteDataService.run(eventUrl, eventValue);
                });
    }

    @Override
    public boolean isFailOnException() {
        return true;
    }

    @Override
    public boolean isFireOnTransactionLifecycleEvent() {
        return true;
    }

    @Override
    public String getOnTransaction() {
        return TransactionState.COMMITTED.name();
    }
}
